(function( ){

	var _present = null;
	var _tokens = null;

	/**
	 * 语法分析主函数
	 * 函数调用代替手动栈
	 * 返回值：
	 * 	[StmtObj,...,StmtObj]
	 * XxxObj对象约定：
	 * 	{
	 * 		type: "<type>"
	 * 		ctnt: []/{}
	 * 	}
	 * 其中_present为counter，指向当前词
	 */
	function parse( tokens ){
		_tokens = tokens;
		_present = counter( );
		return partialParseBlock( );
	}

	/**
	 * 用于报错
	 */
	function error( msg ){
		var token = _tokens[_present.show( )];
		alert( "(row"+token.row+",col"+token.col+") syntax error: "+msg );
	}

	var eat = function( t, c ){
		if(_tokens[_present.show( )].eq( t, c )){
			_present.inc( );
			return true;
		}
		else{
			return false;
		}
	};

	var readList = function( reader, sep, term ){
		if(sep!=""){
			//首项
			if(eat( "mark", term )){
				return true;
			}
			else{
				if(!reader( )){
					return false;
				}
			}
			//后续
			while(eat( "mark", sep )){
				if(!reader( )){
					return false;
				}
			}
			//终结符
			if(!eat( "mark", term )){
				error( "'"+term+"' expected" );
				return false;
			}
		}
		else{
			//后续
			while(!eat( "mark", term )){
				if(!reader( )){
					return false;
				}
			}
		}
		return true;
	};

	/**
	 * 读入块
	 */
	function partialParseBlock( ){
		var rst = [ ];
		while(_present.show( )<_tokens.length){
			//'}'：block结束
			if(_tokens[_present.show( )].eq( "mark", "}" )){
				break;
			}
			else{
				rst.unshift( parseStmt( ) );
				if(rst[0]==null){
					return null;
				}
			}
		}
		return rst.reverse( );
	}

	/**
	 * 读入函数
	 */
	function partialParseFunction( ){
		var rst = {
			args: [ ],
			stmts: null
		};
		//开括号
		if(!eat( "mark", "(" )){
			error( "'(' expected" );
			return null;
		}
		//读入每个元素
		if(!readList( function( ){
			//类型
			var type = parseTypeExpr( );
			if(type==null){
				error( "type expected" );
				return false;
			}
			//变量
			if(_tokens[_present.show( )].type!="id"){
				error( "identifier expected" );
				return false;
			}
			rst.ctnt.args.push( {
				type: type,
				name: _tokens[_present.show( )].ctnt
			} );
			_present.inc( );
			return true;
		}, ",", ")" )){
			return null;
		}
		//开括号
		if(!eat( "mark", "{" )){
			error( "'{' expected" );
			return null;
		}
		//定义块
		rst.ctnt.stmts = partialParseBlock( );
		if(rst.ctnt==null){
			return null;
		}
		//闭括号
		if(!eat( "mark", "}" )){
			error( "'}' expected" );
			return false;
		}
		return rst;
	}

	/**
	 * 读入语句
	 */
	function parseStmt( ){
		var rst = null;
		//读控制语句的条件
		var readCondition = function( ){
			var rst = null;
			if(!eat( "mark", "(" )){
				error( "'(' expected" );
				return null;
			}
			rst = parseExpr( );
			if(rst==null){
				return null;
			}
			if(!eat( "mark", ")" )){
				error( "')' expected" );
				return null;
			}
			return rst;
		};
		//读控制语句的内容
		var readStmtBlock = function( ){
			var rst = null;
			if(eat( "mark", "{" )){
				rst = {
					type: "stmt-block",
					ctnt: partialParseBlock( )
				};
				if(rst.ctnt==null){
					return null;
				}
				if(!eat( "mark", "}" )){
					error( "'}' expected" );
					return null;
				}
			}
			else{
				rst = parseStmt( );
				if(rst==null){
					return null;
				}
			}
			return rst;
		};
		//template开头：TmplDecl
		if(eat( "key", "template" )){
			rst = {
				type: "stmt-tmpl",
				ctnt: {
					name: "",
					args: [ ],
					body: null
				}
			};
			//读入名称
			if(_tokens[_present.show( )].type!="id"){
				error( "identifier expected" );
				return null;
			}
			rst.ctnt.name = _tokens[_present.show( )].ctnt;
			//读入参数
			if(!eat( "mark", "<" )){
				error( "'<' expected" );
				return null;
			}
			if(!readList( function( ){
				//读入名称
				if(_tokens[_present.show( )].type!="id"){
					error( "identifier expected" );
					return false;
				}
				rst.ctnt.args.push( _tokens[_present.show( )].ctnt );
				return true;
			}, ",", ">" )){
				return null;
			}
			//模板函数
			if(eat( "key", "function" )){
				rst.ctnt.body = {
					type: "expr-func",
					ctnt: partialParseFunction( )
				};
				if(rst.ctnt.body.ctnt==null){
					return null;
				}
			}
			//模板类型
			else{
				rst.ctnt.body = parseTypeExpr( );
				if(rst.ctnt.body==null){
					return null;
				}
			}
			//读入';'
			if(!eat( "mark", ";" )){
				error( "';' expected" );
				return null;
			}
		}
		//type开头：TypeDecl
		else if(eat( "key", "type" )){
			rst = {
				type: "stmt-type",
				ctnt: {
					name: "",
					body: null
				}
			};
			//读入名称
			if(_tokens[_present.show( )].type!="id"){
				error( "identifier expected" );
				return null;
			}
			rst.ctnt.name = _tokens[_present.show( )].ctnt;
			//读入类型
			rst.ctnt.body = parseTypeExpr( );
			if(rst.ctnt.body==null){
				return null;
			}
			//读入';'
			if(!eat( "mark", ";" )){
				error( "';' expected" );
				return null;
			}
		}
		//var开头：VarDecl
		else if(eat( "key", "var" )){
			rst = {
				type: "stmt-var",
				ctnt: {
					name: "",
					body: null
				}
			};
			//读入名称
			if(_tokens[_present.show( )].type!="id"){
				error( "identifier expected" );
				return null;
			}
			rst.ctnt.name = _tokens[_present.show( )].ctnt;
			//读入'='
			if(!eat( "mark", "=" )){
				error( "'=' expected" );
				return null;
			}
			//读入值
			rst.ctnt.body = parseExpr( );
			if(rst.ctnt.body==null){
				return null;
			}
			//读入';'
			if(!eat( "mark", ";" )){
				error( "';' expected" );
				return null;
			}
		}
		//if开头：(1)if("Expr")"Stmt"(2)if("Expr")"Stmt"else"Stmt"
		else if(eat( "key", "if" )){
			rst = {
				type: "stmt-ifelse",
				ctnt: {
					condition: null,
					partif: null,
					partelse: null
				}
			};
			//条件部分
			rst.ctnt.condition = readCondition( );
			if(rst.ctnt.condition==null){
				return null;
			}
			//if部分
			rst.ctnt.partif = readStmtBlock( );
			if(rst.ctnt.partif==null){
				return null;
			}
			//else部分
			if(eat( "key", "else" )){
				rst.ctnt.partelse = readStmtBlock( );
				if(rst.ctnt.partelse==null){
					return null;
				}
			}
		}
		//while开头：while("Expr")"Stmt"
		else if(eat( "key", "while" )){
			rst = {
				type: "stmt-ifelse",
				ctnt: {
					condition: null,
					partwhile: null
				}
			};
			//条件部分
			rst.ctnt.condition = readCondition( );
			if(rst.ctnt.condition==null){
				return null;
			}
			//while部分
			rst.ctnt.partwhile = readStmtBlock( );
			if(rst.ctnt.partwhile==null){
				return null;
			}
		}
		//'{'开头：{"Stmt"…"Stmt"}
		else if(eat( "mark", "{" )){
			//读入语句
			rst = {
				type: "stmt-block",
				ctnt: partialParseBlock( )
			};
			//跳过结尾
			if(!eat( "mark", "}" )){
				error( "'}' expected" );
				return null;
			}
		}
		//break开头
		else if(eat( "key", "break" )){
			rst = {
				type: "stmt-break",
				ctnt: null
			};
			//读入';'
			if(!eat( "mark", ";" )){
				error( "';' expected" );
				return null;
			}
		}
		//return开头
		else if(eat( "key", "return" )){
			rst = {
				type: "stmt-return",
				ctnt: null
			};
			//读入值
			rst.ctnt = parseExpr( );
			if(rst.ctnt==null){
				return null;
			}
			//读入';'
			if(!eat( "mark", ";" )){
				error( "';' expected" );
				return null;
			}
		}
		//其他情况：(1)"Expr";(2)"Expr"="Expr";
		else{
			//读入Expr：分号前的部分
			var expr = parseExpr( );
			if(expr==null){
				return null;
			}
			//(1)"Expr";
			if(eat( "mark", ";" )){
				//结果
				rst = {
					type: "stmt-call",
					ctnt: {
						expr: expr
					}
				};
			}
			//(2)"Expr"="Expr";
			else if(eat( "mark", "=" )){
				//读入剩余
				var val = parseExpr( );
				if(val==null){
					return null;
				}
				//读入分号
				if(!eat( "mark", ";" )){
					error( "';' expected" );
					return null;
				}
			}
			else{
				error( "';' expected" );
				return null;
			}
		}
		return rst;
	}

	/**
	 * 读入Expr
	 * 外置限界符{},[],(),function()和后缀.,(),[]在读入时规约
	 * 一元和二元和三元运算符属前缀或中缀，须依照优先级规约
	 */
	function parseExpr( ){
		//表达式初始化
		var read = [ ];

		var prior = [ [ "*", "/", "%" ], [ "+", "-" ], [ "<<", ">>" ], [ ">", "<", ">=", "<=" ], [ "==", "!=" ], [ "&" ], [ "^" ], [ "|" ], [ "&&" ], [ "||" ] ];

		//规约一级运算符
		var reduce = function( st ){
			var rst = null;
			if(st.length>1&&st[0].type.split( "-" )[0]=="expr"&&st[1].type.split( "-" )[1]=="uni"){
				rst = {
					type: "expr-uni",
					ctnt: { }
				};
				rst.ctnt.root = st.shift( );
				rst.ctnt.prefix = st.shift( ).ctnt;
				st.unshift( rst );
				return true;
			}
			else if(st.length>2&&st[0].type.split( "-" )[0]=="expr"&&st[1].type.split( "-" )[1]=="bin"&&st[2].type.split( "-" )[0]=="expr"){
				rst = {
					type: "expr-bin",
					ctnt: { }
				};
				rst.ctnt.right = st.shift( );
				rst.ctnt.op = st.shift( ).ctnt;
				rst.ctnt.left = st.shift( );
				st.unshift( rst );
				return true;
			}
			else if(st.length>4&&st[0].type.split( "-" )[0]=="expr"&&st[1].type.split( "-" )[1]=="tri"&&st[2].type.split( "-" )[0]=="expr"&&st[3].type.split( "-" )[1]=="tri"&&st[4].type.split( "-" )[0]=="expr"){
				rst = {
					type: "expr-tri",
					ctnt: { }
				};
				rst.ctnt.latter = st.shift( );
				st.shift( );
				rst.ctnt.former = st.shift( );
				st.shift( );
				rst.ctnt.condition = st.shift( );
				st.unshift( rst );
				return true;
			}
			else{
				return false;
			}
		};

		//当前符号分类判断
		var isSeperator = function( t ){
			return t.type=="mark"&&has( [ "}", "]", ")", ",", ";" ], t.ctnt );
		};
		var isUni = function( t ){
			return t.type=="mark"&&has( [ "+", "-", "!", "~" ], t.ctnt );
		};
		var isBin = function( t ){
			return t.type=="mark"&&testeach( prior, function( p ){
				return has( p, t.ctnt );
			} );
		};
		var isTri = function( t ){
			return t.type=="mark"&&has( [ ":", "?" ], t.ctnt );
		};
		var isElement = function( t ){
			return t.type=="mark"&&has( [ "{", "[", "(" ], t.ctnt )||t.eq( "key", "function" )||t.eq( "key", "null" )||t.type=="str"||t.type=="num"||t.type=="id";
		};
		var isSuffix = function( t ){
			return t.type=="mark"&&has( [ ".", "[", "(" ], t.ctnt );
		};
		//当前符号分类处理
		var procSeperator = function( ){
			if(reduce( read )){
				return true;
			}
			else if(read.length==1){
				return true;
			}
			else{
				error( "expression unfinished" );
				return false;
			}
		};
		var procUni = function( ){
			read.unshift( {
				type: "op-uni",
				ctnt: _tokens[_present.show( )].ctnt
			} );
			_present.inc( );
			return true;
		};
		var procBin = function( ){
			var shouldReduce = function( op0, op1 ){
				var p0 = -1;
				var p1 = -1;
				loop_break( prior.length, function( p ){
					if(has( prior[p], op0 )){
						p0 = p;
					}
					if(has( prior[p], op1 )){
						p1 = p;
					}
					if(p0<0||p1<0){
						return true;
					}
					else{
						return false;
					}
				} );
				return p0<=p1;
			};
			//一元操作符
			if(read.length>1&&read[1].type=="op-uni"){
				reduce( read );
				return true;
			}
			//二元操作符
			else if(read.length>2&&read[1].type=="op-bin"&&shouldReduce( read[1].ctnt, _tokens[_present.show( )].ctnt )){
				reduce( read );
				return true;
			}
			//不归约时压栈
			else{
				read.unshift( {
					type: "op-bin",
					ctnt: _tokens[_present.show( )]
				} );
				_present.inc( );
				return true;
			}
		};
		var procTri = function( ){
			//一元操作符
			if(read.length>1&&read[1].type=="op-uni"){
				reduce( read );
				return true;
			}
			//二元操作符
			else if(read.length>2&&read[1].type=="op-bin"){
				reduce( read );
				return true;
			}
			//三元操作符
			else if(read.length>4&&read[1].ctnt==":"&&read[3].ctnt=="?"){
				reduce( read );
				return true;
			}
			//不归约时压栈
			else{
				read.unshift( {
					type: "op-tri",
					ctnt: _tokens[_present.show( )]
				} );
				_present.inc( );
				return true;
			}
		};
		var procElement = function( ){
			var rst = null;
			//["Expr",…,"Expr"]
			if(eat( "mark", "[" )){
				rst = {
					type: "expr-arr",
					ctnt: [ ]
				};
				//读入每个元素
				if(!readList( function( ){
					rst.ctnt.unshift( parseExpr( ) );
					if(rst.ctnt[0]==null){
						return false;
					}
					return true;
				}, ",", "]" )){
					return false;
				}
				rst.ctnt.reverse( );
			}
			//{"@VarId":"Expr",…,"@VarId":"Expr"}
			else if(eat( "mark", "{" )){
				rst = {
					type: "expr-obj",
					ctnt: { }
				};
				//读入每个元素
				if(!readList( function( ){
					//字段名
					if(_tokens[_present.show( )].type!="id"){
						error( "identifier expected" );
						return false;
					}
					var name = _tokens[_present.show( )].ctnt;
					_present.inc( );
					//冒号
					if(!eat( "mark", ":" )){
						error( "':' expected" );
						return false;
					}
					//元素
					rst.ctnt[name] = parseExpr( );
					if(rst.ctnt[name]==null){
						return false;
					}
					return true;
				}, ",", "}" )){
					return false;
				}
			}
			//("Expr")
			else if(eat( "mark", "(" )){
				rst = {
					type: "expr-paren",
					ctnt: null
				};
				//读内容
				rst.ctnt = parseExpr( );
				if(rst.ctnt==null){
					return false;
				}
				//闭括号
				if(!eat( "mark", ")" )){
					error( "')' expected" );
					return false;
				}
			}
			//function("TypeExpr""#VarId",…,"TypeExpr""#VarId"){"Stmt"…"Stmt"}
			else if(eat( "key", "function" )){
				rst = {
					type: "expr-func",
					ctnt: partialParseFunction( )
				};
				if(rst.ctnt==null){
					return null;
				}
			}
			//null/null<"TypeExpr">
			else if(eat( "key", "null" )){
				rst = {
					type: "expr-null",
					ctnt: null
				};
				//null带类型的情况
				if(eat( "mark", "<" )){
					rst.ctnt = parseTypeExpr( );
					if(rst.ctnt==null){
						return null;
					}
					//闭括号
					if(!eat( "mark", ">" )){
						error( "'>' expected" );
						return false;
					}
				}
			}
			else{
				//读入终结符
				rst = {
					type: "expr-"+_tokens[_present.show( )].type,
					ctnt: _tokens[_present.show( )].ctnt
				};
				//下一个
				_present.inc( );
			}
			//结果压栈
			read.unshift( rst );
			return true;
		};
		var procSuffix = function( ){
			//弹出根元素
			var rst = {
				type: "",
				ctnt: {
					root: read.shift( ),
					suffix: null
				}
			};
			if(eat( "mark", "." )){
				rst.type = "expr-mbr";
				//读入id
				if(_tokens[_present.show( )].type=="id"){
					error( "identifier expected" );
					return false;
				}
				rst.ctnt.suffix = _tokens[_present.show( )].ctnt;
				_present.inc( );
			}
			else if(eat( "mark", "[" )){
				rst.type = "expr-idx";
				//读入index
				rst.ctnt.suffix = parseExpr( );
				if(rst.ctnt.suffix==null){
					return false;
				}
				//结尾']'
				if(!eat( "mark", "]" )){
					error( "']' expected" );
					return false;
				}
			}
			else if(eat( "mark", "(" )){
				rst.type = "expr-call";
				rst.ctnt.suffix = [ ];
				//读入每个元素
				if(!readList( function( ){
					rst.ctnt.suffix.unshift( parseExpr( ) );
					if(rst.ctnt.suffix[0]==null){
						return false;
					}
					return true;
				}, ",", ")" )){
					return false;
				}
				rst.ctnt.suffix.reverse( );
			}
			//结果压栈
			read.unshift( rst );
			return true;
		};
		var stage = "prefix";
		var now = null;
		//e.g. \pre\!!a\suf\+\root\b\suf\*\root\c\suf\.x[5]-\root\d\suf\;
		while(_present.show( )<_tokens.length){
			now = _tokens[_present.show( )];
			switch(stage){
			case "prefix":
				if(isUni( now )){
					if(!procUni( )){
						return null;
					}
				}
				else if(isElement( now )){
					if(!procElement( )){
						return null;
					}
					stage = "suffix";
				}
				else{
					error( "'"+now+"' unexpected" );
					return null;
				}
				break;
			case "root":
				if(isElement( now )){
					if(!procElement( )){
						return null;
					}
					stage = "suffix";
				}
				else{
					error( "'"+now+"' unexpected" );
					return null;
				}
			case "suffix":
				if(isBin( now )){
					if(!procBin( )){
						return null;
					}
					stage = "root";
				}
				else if(isTri( now )){
					if(!procTri( )){
						return null;
					}
					stage = "root";
				}
				else if(isSuffix( now )){
					if(!procSuffix( now )){
						return null;
					}
				}
				else if(isSeperator( now )){
					if(!procSeperator( )){
						return null;
					}
					if(read.lenth==1){
						return read[0];
					}
				}
				else{
					error( "'"+now+"' unexpected" );
					return null;
				}
				break;
			default:
			}
		}
		//文件结尾
		error( "expression unfinished" );
		return null;
	}

	function parseTypeExpr( ){
		var rst = null;
		var readSig = function( ){

		};
		//读入基声明
		//结构
		if(eat( "mark", "{" )){
			rst = {
				type: "type-struct",
				ctnt: { }
			};
			//读入每个元素
			if(!readList( function( ){
				//类型
				var type = parseTypeExpr( );
				if(type==null){
					return false;
				}
				//字段名
				if(_tokens[_present.show( )].type!="id"){
					error( "identifier expected" );
					return false;
				}
				rst.ctnt[_tokens[_present.show( )].ctnt] = type;
				_present.inc( );
				//分号
				if(!eat( "mark", ";" )){
					error( "':' expected" );
					return false;
				}
				return true;
			}, "", "}" )){
				return null;
			}
		}
		//void
		else if(eat( "key", "void" )){
			rst = {
				type: "type-void",
				ctnt: null
			};
		}
		//名称
		else if(_tokens[_present.show( )].type=="id"){
			rst = {
				type: "type-ref",
				ctnt: _tokens[_present.show( )].ctnt
			};
			_present.inc( );
			//名称为模板的情况
			if(eat( "mark", "<" )){
				rst = {
					type: "type-tmpl",
					ctnt: {
						name: rst.ctnt,
						args: [ ]
					}
				};
				//读入每个元素
				if(!readList( function( ){
					//类型特化
					rst.ctnt.args.unshift( parseTypeExpr( ) );
					if(rst.ctnt.args[0]==null){
						return null;
					}
					return true;
				}, ",", ">" )){
					return null;
				}
				rst.ctnt.args.reverse( );
			}
		}
		else{
			error( "type declaration expected" );
			return null;
		}

		//读入后缀
		while(true){
			if(eat( "mark", "[" )){
				rst = {
					type: "type-arr",
					ctnt: rst
				};
				//闭括号
				if(!eat( "mark", "]" )){
					error( "']' expected" );
					return null;
				}
			}
			else if(eat( "mark", "<=" )){
				rst = {
					type: "type-func",
					ctnt: {
						ret: rst,
						args: [ ]
					}
				};
				//开括号
				if(!eat( "mark", "(" )){
					error( "'(' expected" );
					return null;
				}
				//读入每个元素
				if(!readList( function( ){
					//参数类型
					rst.ctnt.args.unshift( parseTypeExpr( ) );
					if(rst.ctnt.args[0]==null){
						return null;
					}
					return true;
				}, ",", "）" )){
					return null;
				}
				rst.ctnt.args.reverse( );
			}
			else{
				break;
			}
		}
		return rst;
	}

	exports.syntax = parse;

})( );
